namespace feng3d
{

    /**
     * 加载类
     * @author feng 2016-12-14
     */
    export var Loader = {
        /**
         * 加载文本
         */
        loadText: loadText,
        /**
         * 加载二进制
         */
        loadBinary: loadBinary,
        /**
         * 加载图片
         */
        loadImage: loadImage,
    }

    interface LoadItem
    {
        url: string;
        dataFormat: string;
        onCompleted?: (content: string | ArrayBuffer) => void;
        onProgress?: (loaded: number, total: number) => void;
        onError?: (ev: Error) => void;
    }

    /**
     * 加载文本
     * @param url   路径
     */
    function loadText(url: string, onCompleted?: (content: string) => void, onRequestProgress?: () => void, onError?: (e) => void)
    {
        xmlHttpRequestLoad({ url: url, dataFormat: LoaderDataFormat.TEXT, onCompleted: <any>onCompleted, onProgress: onRequestProgress, onError: onError });
    }

    /**
     * 加载二进制
     * @param url   路径
     */
    function loadBinary(url: string, onCompleted?: (content: ArrayBuffer) => void, onRequestProgress?: () => void, onError?: (e) => void)
    {
        xmlHttpRequestLoad({ url: url, dataFormat: LoaderDataFormat.BINARY, onCompleted: <any>onCompleted, onProgress: onRequestProgress, onError: onError });
    }

    /**
     * 加载图片
     * @param url   路径
     */
    function loadImage(url: string, onCompleted?: (content: HTMLImageElement) => void, onRequestProgress?: () => void, onError?: (e) => void)
    {
        var image = new Image();
        image.crossOrigin = "Anonymous";
        image.onload = (event) =>
        {
            onCompleted && onCompleted(image);
        }
        image.onerror = (event) =>
        {
            debuger && error("Error while trying to load texture: " + url);
            //
            image.src = "";
            //
            var err = new Error(url + " 加载失败！");
            onError && onError(err);
        }
        image.src = url;
    }

    /**
     * 使用XMLHttpRequest加载
     * @param url           加载路径
     * @param dataFormat    数据类型
     */
    function xmlHttpRequestLoad(loadItem: LoadItem)
    {
        var request = new XMLHttpRequest();
        request.open('Get', loadItem.url, true);
        request.responseType = loadItem.dataFormat == LoaderDataFormat.BINARY ? "arraybuffer" : "";
        request.onreadystatechange = onRequestReadystatechange(request, loadItem);
        request.onprogress = onRequestProgress(request, loadItem);
        request.send();
    }

    /**
     * 请求进度回调
     */
    function onRequestProgress(request: XMLHttpRequest, loadItem: LoadItem)
    {
        return (event: ProgressEvent) =>
        {
            loadItem.onProgress && loadItem.onProgress(event.loaded, event.total);
        }
    }

    /**
     * 请求状态变化回调
     */
    function onRequestReadystatechange(request: XMLHttpRequest, loadItem: LoadItem)
    {
        return (ev) =>
        {
            if (request.readyState == 4)
            {// 4 = "loaded"

                request.onreadystatechange = <any>null;

                if (request.status >= 200 && request.status < 300)
                {
                    var content = loadItem.dataFormat == LoaderDataFormat.TEXT ? request.responseText : request.response;
                    loadItem.onCompleted && loadItem.onCompleted(content);
                } else
                {
                    var err = new Error(loadItem.url + " 加载失败！");
                    loadItem.onError && loadItem.onError(err);
                }
            }
        }
    }
}